﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using DocumentBuilder.Components;
using DocumentBuilder.Controls.DataSources;
using DocumentBuilder.Controls.Utils;

namespace DocumentBuilder.Controls
{
    public class ItemTemplate
    {
        private const String ResultString = "${value},${type}";
        private static readonly Regex TemplateRegex = new Regex(@"\{Binding\(\s*source\s*:(?<source>[^/]+),\s*value\s*:(?<value>[^/]+),\s*type\s*:(?<type>[^/]+)\)\s+\}", RegexOptions.Compiled);
        private readonly MatchCollection _matches;

        private Document Context { get; set; }
        private XmlNode TemplateNode { get; set; }
        private List<IControl> TemplateChildren { get; set; }

        public string BindsWith { get; private set; }

        private ItemTemplate(Document context, XmlNode templateNode)
        {
            Context = context;
            TemplateNode = templateNode;
            TemplateChildren = new List<IControl>();

            if (TemplateRegex.IsMatch(templateNode.InnerXml))
            {
                _matches = TemplateRegex.Matches(templateNode.InnerXml);
            }

            var bindsWith = String.Empty;
            if (templateNode.Attributes["bindswith"] != null)
                bindsWith = templateNode.Attributes["bindswith"].Value;

            BindsWith = bindsWith;
        }

        public static ItemTemplate Create(Document context, XmlNode templateNode)
        {
            return new ItemTemplate(context, templateNode);
        }

        public String CreateWith(IEvaluable dataItem)
        {
            TemplateChildren = new List<IControl>();

            var html = TemplateNode.InnerXml;
            var indexDiff = 0;

            if (_matches == null)
                return html;

            foreach(Match match in _matches)
            {
                var result = match.Result(ResultString).Split(',');
                var value = dataItem.Eval(result[0].Trim()) ?? "";

                html = html.Substring(0, match.Index + indexDiff)
                            + value
                            + html.Substring(match.Length + match.Index + indexDiff);

                indexDiff -= match.Length - value.Length;
            }

            var modifiedNodeDocument = new XmlDocument();
            modifiedNodeDocument.LoadXml(String.Format("<div>{0}</div>", html));

            ControlBuilder.ParseChildControls(Context, modifiedNodeDocument.FirstChild, TemplateChildren);

            var paintCanvas = new StringBuilder();
            foreach (IControl control in TemplateChildren)
            {
               control.PaintHtmlString(paintCanvas);
            }

            return paintCanvas.ToString();
        }
    }
}